#include <iostream>
#include <utility>
#include <tuple>
#include <cstddef>
#include <array>
#include <vector>
#include <iomanip>
#include <sstream>
template <typename... Args>
void Print(const Args &...args)
{
    ((std::cout << args << " "), ...);
    std::cout << std::endl;
}

template <typename... Args>
void PrintWithSep(const std::string &sep, const Args &...args)
{
    ((std::cout << args << sep), ...);
    std::cout << std::endl;
}

struct Employee
{
    std::string name = "Unknown";
    int id = -1;
    double salary = 0.0;
};
/**
 * 推荐使用std::make_unique进行创建unique_ptr对象
 * 他能保证即使异常被抛出时也能安全释放已经分配的资源
 * C++20提供了不初始化的构造unique_ptr的函数
 * std::make_unique_for_overwrite
 */

template <typename T, T... ints>
void Print_sequence(int id, std::integer_sequence<T, ints...> int_seq)
{
    std::cout << id << ") 大小为 " << int_seq.size() << " 的序列：";
    ((std::cout << ints << " "), ...);
    std::cout << "\n";
}

void test1()
{
    Print_sequence(1, std::integer_sequence<unsigned, 1, 2, 3, 4, 5, 6>{});
    Print_sequence(2, std::make_integer_sequence<int, 12>{});
    Print_sequence(3, std::make_index_sequence<10>{});
    Print_sequence(4, std::index_sequence_for<std::ios, float, signed, char>{});
}

template <typename... Args, std::size_t... Indics>
void print_tuple_impl(const std::tuple<Args...> &t, std::index_sequence<Indics...>)
{
    ((std::cout << std::get<Indics>(t) << " "), ...);
    std::cout << std::endl;
}

template <typename... Args>
void print_tuple(const std::tuple<Args...> &t)
{
    print_tuple_impl(t, std::index_sequence_for<Args...>());
}

void test2()
{
    std::tuple t = std::make_tuple(10, 2.8, 'c', "dd");
    std::cout << "元组内容：";
    print_tuple(t);
}

template <typename Array, std::size_t... Indics>
void print_array_impl(const Array &a, std::index_sequence<Indics...>)
{
    ((std::cout << a[Indics] << " "), ...);
    std::cout << std::endl;
}

template <typename T, std::size_t N>
void print_array(const std::array<T, N> &a)
{
    print_array_impl(a, std::make_index_sequence<N>{});
}
void test3()
{
    std::array<int, 5> arr{1, 2, 3, 4, 5};
    print_array(arr);
}

// std::index_sequence<Indics...>它的参数必须都是常量，不允许出现运行时才能确定的参数

// template <typename vec, std::size_t... Indics>
// void print_vector_impl(const vec &v, std::index_sequence<Indics...>)
// {
//     ((std::cout << v[Indics] << " "), ...);
//     std::cout << std::endl;
// }

// template <typename T>
// void print_vec(const std::vector<T> &v)
// {
//     // print_vector_impl(v, std::make_index_sequence<v.size()>{});
//     for (const auto &elem : v)
//         std::cout << elem << " ";
//     std::cout << std::endl;
// }
// void test4()
// {
//     std::vector<int> vec{1, 2, 3, 4, 5};
//     print_vec(vec);
// }

// std::quoted,用于简化带引号字符串的输入输出操作
/**
 * 输出时：自动为字符串添加引号
 * 输入时，自动删除字符串周围的引号
 * 处理转义字符：自动处理 引号内的转义序列
 */

#define pend (printf("\n"))
void test5()
{
    std::string str = "hello world!";
    std::string str1 = "\"hello world!\"";
    PrintWithSep(" ", str, std::quoted(str));
    pend;
    PrintWithSep(" ", str1, std::quoted(str1));
    pend;

    std::istringstream input(str1);
    input >> std::quoted(str1);
    // input >> str1;
    std::cout << "Extracted: " << str1 << std::endl;
}

void test6()
{
    std::string text = "It's a \"text";
    std::cout << "default : " << std::quoted(text) << "\n";
    // 使用单引号替代分隔符
    // \" 使用\替代字符串中的"
    // 如果是'#',就是使用在字符串的前后添加#
    std::cout << "single : " << std::quoted(text, '#') << "\n";

    std::string complex = R"(he said "hello" and left)";
    // 自动对分隔符进行转义
    std::cout << "default : " << std::quoted(complex) << "\n";

    std::stringstream ss1;
    ss1 << std::quoted(complex);
    PrintWithSep("\n", complex);

    std::string tmp1;
    ss1 >> std::quoted(tmp1);
    Print("tmp1: ", tmp1);

    std::stringstream ss2;
    ss2 << std::quoted("Line\nLine2\tTabbled");
    ss2 << std::quoted(text);

    Print("Original: ", text);
    Print("Quoted: ", ss2.str());
    ss2 >> std::quoted(tmp1);
    Print("tmp1: ", tmp1);
}
struct Config
{
    std::string username;
    std::string password;
    std::string server;
    int id;
};
std::string serializeConfig(const Config &con)
{
    std::ostringstream oss;
    oss << std::quoted(con.username) << " "
        << std::quoted(con.password) << " "
        << std::quoted(con.server) << " "
        << con.id;
    return oss.str();
}
Config deserializeConfig(const std::string &str)
{
    std::istringstream iss(str);
    Config con;
    iss >> std::quoted(con.username) >> std::quoted(con.password) >> std::quoted(con.server) >> con.id;
    return con;
}
void test7()
{
    Config original{"admin hello", "pssword@.com", "example.com", 1};
    // 序列化

    std::string serialized = serializeConfig(original);
    std::cout << "Serialized: " << serialized << "\n";
    // 反序列化

    Config restored = deserializeConfig(serialized);
    std::cout << "Restored values:\n"
              << "Username: " << restored.username << "\n"
              << "Password: " << restored.password << "\n"
              << "Server: " << restored.server << "\n"
              << "Id: " << restored.id << "\n";
}

int main()
{
    // Employee e1 = {"xxx", 1, 1.1};
    // // C++ 14
    // Employee e2{"John"};
    // // name="John", id=-1, salary=0.0
    // Employee e3{"Alice", 123}; // name="Alice", id=123, salary=0.0
    // Employee e4{};
    // // C++20支持，不需要严格按照定义顺序赋值
    // Employee e5{.id = {1}, .salary{1.1}};
    // test1();
    // test2();
    // test3();
    // test4();
    // test5();
    // test6();
    test7();
}